﻿using Abp.Application.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using KelonProud.Administration.Domain.Authorization;
using KelonProud.Administration.Dtos;
using KelonProud.Mvc;
using Abp.Domain.Repositories;
using Abp.Web.Models;
using KelonProud.Administration.Dtos.SearchDto;
using KelonProud.Administration.Managers.Authorization;

namespace KelonProud.Administration.Services
{
    public interface IRoleAppService : IAsyncCrudAppService<RoleOutPutDto, int, PagedResultRequestDto, RoleInputDto, RoleInputDto>
    {
        // Task<ListResultDto<PermissionOutputDto>> GetAllPermissions();

        Task<RoleSearchOutput> GetRoles(RoleSearchInput searchInput);

        void DeleteRoleByIds(string ids);
    }

    [WrapResult(WrapOnSuccess = false)]
    public class RoleAppService : KelonProudAsyncCrudAppService<Role, RoleOutPutDto, int, PagedResultRequestDto, RoleInputDto, RoleInputDto>,IRoleAppService
    {
        private readonly RoleManager _roleManager;
        private readonly UserManager _userManager;

        public RoleAppService(IRepository<Role, int> repository, RoleManager roleManager, UserManager userManager) : base(repository)
        {
            _roleManager = roleManager;
            _userManager = userManager;
        }

        public override async Task<RoleOutPutDto> Save(RoleInputDto input)
        {
            var role = await _roleManager.GetRoleByIdAsync(input.Id) ?? new Role();

            role.Name = input.Name;
            role.DisplayName = input.DisplayName;
            role.Description = input.Description;
            role.Navigations = new List<NavigationRole>();
            role.TenantId = input.TenantId;

            role.SetNormalizedName();

            role.Id =  await _roleManager.SaveRoleAsync(role);

            _roleManager.SetNavigations(role, input.NavigationIds);

            return role.MapTo<RoleOutPutDto>();
        }

        public override async Task Delete(EntityDto<int> input)
        {
           

            await base.Delete(input);
        }

        public Task<RoleSearchOutput> GetRoles(RoleSearchInput searchInput)
        {
            var result = new RoleSearchOutput() { };
            var query = _roleManager.Query;

            if (searchInput.SearchStr.HasValue())
                query = query.Where(w =>
                    w.Name.Contains(searchInput.SearchStr) || w.DisplayName.Contains(searchInput.SearchStr));

            result.Total = query.Count();
            result.Rows = query.ToList().Select(s => s.MapTo<RoleOutPutDto>()).ToList();

            return Task.FromResult(result);
        }

        public void DeleteRoleByIds(string ids)
        {
            if (ids.HasValue())
            {
                var idList = ids.Split(',');
                idList.Each( e =>
                {
                    var role = _roleManager.Query.FirstOrDefault(f=>f.Id.ToString()==e);

                    if (role != null)
                    {
                        if (role.Navigations.Any())
                            throw new Exception("角色有菜单关联，不能被删除！");

                        if (_roleManager.UserRoles.Any(a => a.RoleId.ToString() == e))
                            throw new Exception("角色有用户关联，不能被删除！");

                        _roleManager.DeleteRole(role);
                    }
                });
            }
        }
    }
}
